package org.springframework.orm.jpa.persistenceunit;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

/**
 * <p></p>
 *
 * @author linhx
 * @date 2022/3/9
 */
public class PerfMonXformer implements ClassFileTransformer {

	@Override
	public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
		byte[] transformed = null;
		System.out.println("Transforming:" + className);
		ClassPool pool = ClassPool.getDefault();
		CtClass cl = null;
		try {
			cl = pool.makeClass(new ByteArrayInputStream(classfileBuffer));
			if (cl.isInterface() == false) {
				CtBehavior[] methods = cl.getDeclaredBehaviors();
				for (int i = 0; i < methods.length; i++) {
					if (methods[i].isEmpty() == false) {
						// 修改method字节码
						doMethod(methods[i]);
					}
				}
				transformed = cl.toBytecode();
			}
		} catch (IOException | CannotCompileException e) {
			System.err.println("Could not instrument " +  className +", exception:"+e.getMessage());
		}finally {
			if(cl != null) cl.defrost();
		}
		return transformed;
	}

	private void doMethod(CtBehavior method) throws CannotCompileException {
		method.insertBefore("long stime = System.nanoTime();");
		method.insertAfter("System.out.println(\"leave "+method.getName()
				+" and time:\"+(System.nonoTime() - stime))");
	}
}
